home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Magazine / C_Tutorial / Part-6 / asl1a.c < prev    next >
C/C++ Source or Header  |  1997-10-27  |  19KB  |  760 lines

  1. #include "iff.h"
  2.  
  3. #include<exec/libraries.h>
  4. #include<intuition/intuition.h>
  5. #include<utility/tagitem.h>
  6. #include<graphics/text.h>
  7. #include<graphics/rastport.h>
  8. #include<intuition/screens.h>
  9. #include<libraries/gadtools.h>
  10. #include<libraries/asl.h>
  11. #include<exec/memory.h>
  12.  
  13. #include<string.h>
  14. #include<stdio.h>
  15.  
  16. #include<clib/exec_protos.h>
  17. #include<clib/graphics_protos.h>
  18. #include<clib/intuition_protos.h>
  19. #include<clib/gadtools_protos.h>
  20. #include<clib/asl_protos.h>
  21. #include<clib/dos_protos.h>
  22.  
  23. /* The library base global variables */
  24. /* (The different style of opening libraries requires these to be initialised to NULL) */
  25. struct Library* GfxBase = NULL;
  26. struct Library* IntuitionBase = NULL;
  27. struct Library* GadToolsBase = NULL;
  28. struct Library* AslBase = NULL;
  29. struct Library* DosBase = NULL;
  30. struct Library* IFFBase = NULL;
  31.  
  32. /* The global handle on the palette gadget */
  33. struct Gadget* palgad = NULL;
  34. /* Global record of foreground pen */
  35. UBYTE pen;
  36. /* Global records of our windows */
  37. struct Window* drawwin = NULL;
  38. struct Window* toolwin = NULL;
  39. /* Global record of title bar height */
  40. int offtop;
  41. /* Global record of our menu strip */
  42. struct Menu* menustrip = NULL;
  43. /* Global record of the screen's visual information */
  44. APTR vinfo = NULL;
  45. /* Initialised structure declaration: describes 8pt Topaz font */
  46. struct TextAttr topazFont = { "topaz.font", 8, 0, 0, };
  47. /* Global record of our gadget list */
  48. struct Gadget* glist = NULL;
  49. /* Global record of our screen */
  50. struct Screen* scr = NULL;
  51. /* Global handles for our requesters */
  52. struct FileRequester* loadreq = NULL;
  53. struct FileRequester* savereq = NULL;
  54. /* Global handle for our bitmap */
  55. struct BitMap* bitmap = NULL;
  56.  
  57. /* Need to give prototypes for our functions */
  58. int  createAll();
  59. void freeAll();
  60. int  openLibs();
  61. void closeLibs();
  62. int  openScr();
  63. void closeScr();
  64. int  createMenuStrip();
  65. void freeMenuStrip();
  66. int  openToolWin();
  67. void closeToolWin();
  68. int  openDrawWin();
  69. void closeDrawWin();
  70. int  createGadgets();
  71. void freeGadgets();
  72. void handleIDCMP();
  73. int  checkToolWin();
  74. void setFgPen(int);
  75. void doGadgetUp(UWORD, struct Gadget*);
  76. int  doMenuPick(UWORD);
  77. void freeReqs();
  78. void load();
  79. void save();
  80. int  createBitmap();
  81. void freeBitmap();
  82.  
  83. /* Some constants for the position and size of our gadget */
  84. #define MYBUT_LEFT        (10)
  85. #define MYBUT_TOP            (5)
  86. #define MYBUT_WIDTH        (80)
  87. #define MYBUT_HEIGHT    (12)
  88. #define MYBUT_TEXT        "Next Pen"
  89. #define MYBUT_ID            (0)
  90.  
  91. #define MYPAL_LEFT        (170)
  92. #define MYPAL_TOP            (1)
  93. #define MYPAL_WIDTH        (109)
  94. #define MYPAL_HEIGHT    (19)
  95. #define MYPAL_TEXT        "Colour:"
  96. #define MYPAL_ID            (1)
  97. #define MYPAL_DEPTH        (4)
  98.  
  99. /* The top gap required around the gadgets */
  100. #define MYTOPGAP      (21)
  101.  
  102. /* The initial pen colour */
  103. #define MYINITPEN            (1)
  104.  
  105. /* The size of our filename string */
  106. #define MAXFILENAME        (300)
  107.  
  108. /* The start of the program */
  109. void main()
  110. {
  111.     /* Use a different style of opening libraries... */
  112.     if(createAll())
  113.     {
  114.         /* Now do the real work */
  115.         handleIDCMP();
  116.     }
  117.     /* Matched call to close libraries */
  118.     freeAll();
  119. }
  120.  
  121. int createAll()
  122. {
  123.     return openLibs() && openScr() && createBitmap() && createMenuStrip() && createGadgets() && openToolWin() && openDrawWin();
  124. }
  125.  
  126. void freeAll()
  127. {
  128.     freeReqs();
  129.     closeDrawWin();
  130.     closeToolWin();
  131.     freeGadgets();
  132.     freeMenuStrip();
  133.     freeBitmap();
  134.     closeScr();
  135.     closeLibs();
  136. }
  137.  
  138. /* Try to open all the libraries -- return TRUE on success */
  139. int openLibs()
  140. {
  141.     if((GfxBase = OpenLibrary("graphics.library",37)) == NULL)
  142.     {
  143.         printf("Error: could not open graphics.library\n");
  144.         return FALSE;
  145.     }
  146.     if((IntuitionBase = OpenLibrary("intuition.library",37)) == NULL)
  147.     {
  148.         printf("Error: could not open intuition.library\n");
  149.         return FALSE;
  150.     }
  151.     if((GadToolsBase = OpenLibrary("gadtools.library",37)) == NULL)
  152.     {
  153.         printf("Error: could not open gadtools.library\n");
  154.         return FALSE;
  155.     }
  156.     if((AslBase = OpenLibrary("asl.library",37)) == NULL)
  157.     {
  158.         printf("Error: could not open asl.library\n");
  159.         return FALSE;
  160.     }
  161.     if((DosBase = OpenLibrary("dos.library",37)) == NULL)
  162.     {
  163.         printf("Error: could not open dos.library\n");
  164.         return FALSE;
  165.     }
  166.     if((IFFBase = OpenLibrary("iff.library",23)) == NULL)
  167.     {
  168.         printf("Error: could not open iff.library\n");
  169.         return FALSE;
  170.     }
  171.   return TRUE;
  172. }
  173.  
  174. /* Close any open library */
  175. void closeLibs()
  176. {
  177.     if(IFFBase)
  178.         CloseLibrary(IFFBase);
  179.     if(DosBase)
  180.         CloseLibrary(DosBase);
  181.     if(AslBase)
  182.         CloseLibrary(AslBase);
  183.     if(GadToolsBase)
  184.         CloseLibrary(GadToolsBase);
  185.     if(IntuitionBase)
  186.         CloseLibrary(IntuitionBase);
  187.     if(GfxBase)
  188.         CloseLibrary(GfxBase);
  189. }
  190.  
  191. /* Open screen and setup GadTools stuff */
  192. int openScr()
  193. {
  194.     UWORD pens[] = { ~0 };
  195.     /* Try to open a new screen with 16 colours (four bitplanes deep) */
  196.     if(scr = OpenScreenTags(NULL,
  197.                                                     SA_Depth,    4,
  198.                                                     /* Enable 3D look by specifying SA_Pens */
  199.                                                     SA_Pens,    pens,
  200.                                                     SA_Title,    "Hello World Painter",
  201.                                                     TAG_DONE))
  202.     {
  203.         /* Get the visual info so GadTools can render the gadgets nicely */
  204.         if(vinfo = GetVisualInfo(scr, TAG_DONE))
  205.             /* Succeeded */
  206.             return TRUE;
  207.         else
  208.             printf("Error: could not get visual info\n");
  209.     }
  210.     else
  211.         printf("Error: could not create screen\n");
  212.     /* Failed */
  213.     return FALSE;
  214. }
  215.  
  216. void closeScr()
  217. {
  218.     if(vinfo)
  219.     {
  220.         FreeVisualInfo(vinfo);
  221.         vinfo = NULL;
  222.     }
  223.     if(scr)
  224.     {
  225.         CloseScreen(scr);
  226.         scr = NULL;
  227.     }
  228. }
  229.  
  230. /* Create the menu strip, using GadTools menu functions */
  231. int createMenuStrip()
  232. {
  233.     /* The description of our menus */
  234.     struct NewMenu mymenu[] =
  235.     {
  236.         { NM_TITLE, "Project",            0,        0, 0, 0,},
  237.         {  NM_ITEM,        "Load",                "L",    0, 0, 0,},
  238.         {  NM_ITEM,        "Save",                "S",    0, 0, 0,},
  239.         {  NM_ITEM,        NM_BARLABEL,    0,        0, 0, 0,},
  240.         {  NM_ITEM,        "Quit",                "Q",    0, 0, 0,},
  241.         { NM_TITLE, "Pen",                    0,        0, 0, 0,},
  242.         {  NM_ITEM,        "Next",                "N",    0, 0, 0,},
  243.         {  NM_ITEM,        "Prev",                "P",    0, 0, 0,},
  244.         {  NM_ITEM,        NM_BARLABEL,    0,        0, 0, 0,},
  245.         {  NM_ITEM,        "Reset",            "R",    0, 0, 0,},
  246.         { NM_TITLE, "Tools",                0,        0, 0, 0,},
  247.         {  NM_ITEM,        "Screen Bar",    "C",    CHECKIT | MENUTOGGLE | CHECKED, 0, 0,},
  248.         {  NM_ITEM,        "Tool Bar",        "T",    CHECKIT | MENUTOGGLE | CHECKED, 0, 0,},
  249.         {   NM_END, NULL,                        0,        0, 0, 0,},
  250.     };
  251.     if (menustrip = CreateMenus(mymenu, TAG_END))
  252.     {
  253.         if (LayoutMenus(menustrip, vinfo, TAG_END))
  254.             /* Succeeded */
  255.             return TRUE;
  256.         else
  257.             printf("Error: could not layout menus\n");
  258.     }
  259.     else
  260.         printf("Error: could not create menu strip\n");
  261.     /* Failed */
  262.     return FALSE;
  263. }
  264.  
  265. void freeMenuStrip()
  266. {
  267.     if(menustrip)
  268.     {
  269.         FreeMenus(menustrip);
  270.         menustrip = NULL;
  271.     }
  272. }
  273.  
  274. /* Actually open the windows, in the normal way */
  275. int openToolWin()
  276. {
  277.     /* Extra protection -- only open if not already open */
  278.     if(toolwin == NULL)
  279.     {
  280.         /* The minimal height of our tool window */
  281.         int h = MYTOPGAP + offtop + scr->WBorBottom;
  282.         /* Open our tool window */
  283.         if(toolwin = OpenWindowTags(NULL,
  284.                                                                 WA_Left,                    0,
  285.                                                                 WA_Top,                        scr->Height - h,
  286.                                                                 /* Make the window sit in the bottom of the screen */
  287.                                                                 WA_Width,                    scr->Width,
  288.                                                                 WA_Height,                h,
  289.                                                                 WA_Flags,                    WFLG_CLOSEGADGET | WFLG_DRAGBAR,
  290.                                                                 WA_IDCMP,                    IDCMP_CLOSEWINDOW | BUTTONIDCMP | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK,
  291.                                                                 WA_Gadgets,                glist,
  292.                                                                 WA_CustomScreen,    scr,
  293.                                                                 WA_Title,                    "Tools",
  294.                                                                 TAG_DONE,                    0))
  295.         {
  296.             /* Attach menu strip to tool window, as well */
  297.             if(SetMenuStrip(toolwin, menustrip))
  298.             {
  299.                 /* Let GadTools refresh its bits of the tool window */
  300.                 GT_RefreshWindow(toolwin, NULL);
  301.                 return TRUE;
  302.             }
  303.             else
  304.                 printf("Error: could not attach menus to tool window\n");
  305.         }
  306.         else
  307.             printf("Error: could not open tool window\n");
  308.     }
  309.     else
  310.         printf("Warning: tool window already open\n");
  311.     return FALSE;
  312. }
  313.  
  314. void closeToolWin()
  315. {
  316.     if(toolwin)
  317.     {
  318.         ClearMenuStrip(toolwin);
  319.         CloseWindow(toolwin);
  320.         toolwin = NULL;
  321.     }
  322. }
  323.  
  324. int openDrawWin()
  325. {
  326.     /* Open our drawing window */
  327.     if(drawwin = OpenWindowTags(NULL,
  328.                                                             WA_Left,                    0,
  329.                                                             WA_Top,                        0,
  330.                                                             /* Make the window the same size as the screen */
  331.                                                             WA_Width,                    scr->Width,
  332.                                                             WA_Height,                scr->Height,
  333.                                                             WA_Flags,                    WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_REPORTMOUSE | WFLG_SUPER_BITMAP,
  334.                                                             WA_IDCMP,                    IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK,
  335.                                                             WA_CustomScreen,    scr,
  336.                                                             WA_SuperBitMap,        bitmap,
  337.                                                             TAG_DONE,                    0))
  338.     {
  339.         /* Clear our window, since our new bitmap may not be cleared already */
  340.         SetRast(drawwin->RPort, 0);
  341.         /* Set the drawing mode to draw only the foreground of text, not the background */
  342.         SetDrMd(drawwin->RPort, JAM1);
  343.         /* Attach menu strip to drawing window */
  344.         if(SetMenuStrip(drawwin, menustrip))
  345.             return TRUE;
  346.         else
  347.             printf("Error: could not attach menus to drawing window\n");
  348.     }
  349.     else
  350.         printf("Error: could not open drawing window\n");
  351.     return FALSE;
  352. }
  353.  
  354. void closeDrawWin()
  355. {
  356.     if(drawwin)
  357.     {
  358.         ClearMenuStrip(drawwin);
  359.         CloseWindow(drawwin);
  360.         drawwin = NULL;
  361.     }
  362. }
  363.  
  364. int createGadgets()
  365. {
  366.     struct Gadget* gad;
  367.     int offleft;
  368.     struct NewGadget newgad;
  369.     /* Start a GadTools gadget list */
  370.     gad = CreateContext(&glist);
  371.     /* The offsets of our window borders */
  372.     offleft = scr->WBorLeft;
  373.     offtop = scr->WBorTop + (scr->Font->ta_YSize + 1);
  374.  
  375.     /* Setup our first gadget */
  376.     newgad.ng_TextAttr         = &topazFont;
  377.     newgad.ng_VisualInfo     = vinfo;
  378.     newgad.ng_LeftEdge         = MYBUT_LEFT + offleft;
  379.     newgad.ng_TopEdge         = MYBUT_TOP + offtop;
  380.     newgad.ng_Width             = MYBUT_WIDTH;
  381.     newgad.ng_Height             = MYBUT_HEIGHT;
  382.     newgad.ng_GadgetText    = MYBUT_TEXT;
  383.     newgad.ng_GadgetID        = MYBUT_ID;
  384.     newgad.ng_Flags                = 0;
  385.     /* Now create it and add it to our list */
  386.     gad = CreateGadget(BUTTON_KIND, gad, &newgad, TAG_END);
  387.  
  388.     /* Setup our second gadget */
  389.     /* (We can reuse newgad, and just change the different bits) */
  390.     newgad.ng_LeftEdge         = MYPAL_LEFT + offleft;
  391.     newgad.ng_TopEdge         = MYPAL_TOP + offtop;
  392.     newgad.ng_Width             = MYPAL_WIDTH;
  393.     newgad.ng_Height             = MYPAL_HEIGHT;
  394.     newgad.ng_GadgetText    = MYPAL_TEXT;
  395.     newgad.ng_GadgetID        = MYPAL_ID;
  396.     newgad.ng_Flags                = 0;
  397.     /* Now create it and add it to our list */
  398.     gad = CreateGadget(    PALETTE_KIND, gad, &newgad,
  399.                                             /* Initially selected pen */
  400.                                             GTPA_Color, MYINITPEN,
  401.                                             /* Depth: 2 to the power MYPAL_DEPTH colours */
  402.                                             GTPA_Depth, MYPAL_DEPTH,
  403.                                             /* Gadget will indicate selection */
  404.                                             GTPA_IndicatorWidth, 16,
  405.                                             TAG_DONE);
  406.  
  407.     /* Remember gadget pointer so we can affect it in message handler */
  408.     palgad = gad;
  409.     /* Success if we managed final allocation */
  410.     return (gad != NULL);
  411. }
  412.  
  413. void freeGadgets()
  414. {
  415.     if(glist)
  416.     {
  417.         FreeGadgets(glist);
  418.         glist = NULL;
  419.         /* Reset palgad pointer, too */
  420.         palgad = NULL;
  421.     }
  422. }
  423.  
  424. /* Our message handling code */
  425. void handleIDCMP()
  426. {
  427.     char* text = "Hello World!";
  428.     int going = TRUE;
  429.     int drawing = FALSE;
  430.     ULONG drawsig, toolsig, gotsig;
  431.     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  432.     setFgPen(MYINITPEN);
  433.     while(going)
  434.     {
  435.         struct IntuiMessage* intuimsg;
  436.         /* Only include tool window signal mask if window is open */
  437.         toolsig = toolwin ? 1 << toolwin->UserPort->mp_SigBit : 0;
  438.         /* Wait for messages to arrive */
  439.         gotsig = Wait(drawsig | toolsig);
  440.         /* Messages have arrived: loop through all of them */
  441.         /* Check messages from the drawing window first */
  442.         if(gotsig & drawsig)
  443.         {
  444.             while(intuimsg = GT_GetIMsg(drawwin->UserPort))
  445.             {
  446.                 /* Copy the important bits of the message */
  447.                 ULONG class = intuimsg->Class;
  448.                 UWORD code = intuimsg->Code;
  449.                 WORD mousex = intuimsg->MouseX;
  450.                 WORD mousey = intuimsg->MouseY;
  451.                 /* Reply when finished copying bits from message */
  452.                 GT_ReplyIMsg(intuimsg);
  453.                 /* Act on this message... */
  454.                 switch(class)
  455.                 {
  456.                 case IDCMP_MOUSEBUTTONS:
  457.                     switch(code)
  458.                     {
  459.                     case SELECTDOWN:
  460.                         drawing = TRUE;
  461.                         break;
  462.                     case SELECTUP:
  463.                         drawing = FALSE;
  464.                         break;
  465.                     }
  466.                     /* break; omitted so we draw on click, too */
  467.                 case IDCMP_MOUSEMOVE:
  468.                     if(drawing)
  469.                     {
  470.                         Move(drawwin->RPort, mousex, mousey);
  471.                         Text(drawwin->RPort, text, strlen(text));
  472.                     }
  473.                     break;
  474.                 case IDCMP_MENUPICK:
  475.                     going = doMenuPick(code);
  476.                     break;
  477.                 }
  478.             }
  479.         }
  480.         /* Now check messages from the tool window */
  481.         if(going && (gotsig & toolsig))
  482.         {
  483.             while(toolwin && (intuimsg = GT_GetIMsg(toolwin->UserPort)))
  484.             {
  485.                 /* Copy the important bits of the message */
  486.                 ULONG class = intuimsg->Class;
  487.                 UWORD code = intuimsg->Code;
  488.                 APTR iaddr = intuimsg->IAddress;
  489.                 /* Reply when finished copying bits from message */
  490.                 GT_ReplyIMsg(intuimsg);
  491.                 /* Act on this message... */
  492.                 switch(class)
  493.                 {
  494.                 case IDCMP_CLOSEWINDOW:
  495.                     {
  496.                         struct MenuItem* item;
  497.                         /* Close tool window */
  498.                         closeToolWin();
  499.                         /* Unset menu check mark */
  500.                         /* First, remove menu strip from drawing window */
  501.                         ClearMenuStrip(drawwin);
  502.                         /* Menu 2, Item 1 is Tool Bar */
  503.                         item = ItemAddress(menustrip, FULLMENUNUM(2,1,0));
  504.                         /* Unset CHECKED flag */
  505.                         item->Flags &= ~CHECKED;
  506.                         /* Reattach menu strip to drawing window */
  507.                         ResetMenuStrip(drawwin,menustrip);
  508.                         break;
  509.                     }
  510.                 case IDCMP_REFRESHWINDOW:
  511.                     /* You *MUST* remember to ask for and handle these refresh messages */
  512.                     GT_BeginRefresh(toolwin);
  513.                     GT_EndRefresh(toolwin, TRUE);
  514.                     break;
  515.                 case IDCMP_GADGETUP:
  516.                     doGadgetUp(code, (struct Gadget*)iaddr);
  517.                     break;
  518.                 case IDCMP_MENUPICK:
  519.                     going = doMenuPick(code);
  520.                     break;
  521.                 }
  522.             }
  523.         }
  524.     }
  525. }
  526.  
  527. /* Set foreground pen of drawing window */
  528. void setFgPen(int value)
  529. {
  530.     /* Wrap when reached the end of the palette gadget's colours */
  531.     pen = value % (1<<MYPAL_DEPTH);
  532.     /* Only set pen if window is open */
  533.     if(drawwin)
  534.         SetAPen(drawwin->RPort, pen);
  535.     /* If the palette gadget has been made, update it with new pen value */
  536.     if(palgad)
  537.         GT_SetGadgetAttrs(palgad, toolwin, NULL, GTPA_Color, pen, TAG_DONE);
  538. }
  539.  
  540. /* Process IDCMP_GADGETUP event */
  541. void doGadgetUp(UWORD code, struct Gadget* gad)
  542. {
  543.     switch(gad->GadgetID)
  544.     {
  545.     case MYBUT_ID:
  546.         /* Our button was clicked!  Set foreground to next pen colour */
  547.         setFgPen(pen+1);
  548.         break;
  549.     case MYPAL_ID:
  550.         /* Our palette gadget was clicked!  Set foreground to gadget colour */
  551.         setFgPen(code);
  552.         break;
  553.     }
  554. }
  555.  
  556. /* Process IDCMP_MENUPICK event */
  557. int doMenuPick(UWORD code)
  558. {
  559.     UWORD menuCode, menuNumber, itemNumber;
  560.     /* Loop over all the menu selections in the menu code */
  561.     struct MenuItem* item;
  562.     for(menuCode = code;
  563.             menuCode != MENUNULL;
  564.             menuCode = item->NextSelect)
  565.     {
  566.         item = ItemAddress(menustrip, menuCode);
  567.         /* Extract the menu number and menu item number from the menu code */
  568.         menuNumber = MENUNUM(menuCode);
  569.         itemNumber = ITEMNUM(menuCode);
  570.         /* Now decide what to do based on what menu item was selected */
  571.         switch(menuNumber)
  572.         {
  573.         case 0:  /* Project menu */
  574.             /* Only one item: Quit */
  575.             switch(itemNumber)
  576.             {
  577.             case 0:  /* Load */
  578.                 load();
  579.                 break;
  580.             case 1:  /* Save */
  581.                 save();
  582.                 break;
  583.             case 3:  /* Quit (item 2 is the bar!) */
  584.                 return FALSE;
  585.             }
  586.             break;
  587.         case 1:  /* Pen menu */
  588.             switch(itemNumber)
  589.             {
  590.             case 0:  /* Next */
  591.                 setFgPen(pen+1);
  592.                 break;
  593.             case 1:  /* Prev */
  594.                 setFgPen(pen-1);
  595.                 break;
  596.             case 3:  /* Reset (item 2 is the bar!) */
  597.                 setFgPen(MYINITPEN);
  598.                 break;
  599.             }
  600.             break;
  601.         case 2:  /* Tools menu */
  602.             switch(itemNumber)
  603.             {
  604.             case 0:  /* Screen Bar */
  605.                 ShowTitle(scr, item->Flags & CHECKED);
  606.                 break;
  607.             case 1:  /* Tool Bar */
  608.                 /* Do the open or close */
  609.                 if(item->Flags & CHECKED)
  610.                 {
  611.                     /* If the open fails, stop immediately */
  612.                     if(!openToolWin())
  613.                         return FALSE;
  614.                 }
  615.                 else
  616.                     closeToolWin();
  617.                 break;
  618.             }
  619.         }
  620.     }
  621.     /* Keep going */
  622.     return TRUE;
  623. }
  624.  
  625. /* Open an ASL load file requester */
  626. void load()
  627. {
  628.     /* Allocate the requester if we haven't already */
  629.     if(loadreq == NULL)
  630.         loadreq = (struct FileRequester*)AllocAslRequest(ASL_FileRequest,NULL);
  631.     if(loadreq)
  632.     {
  633.         if(AslRequestTags(loadreq,
  634.                                             ASLFR_TitleText,            "Load File",
  635.                                             ASLFR_Window,                    drawwin,
  636.                                             ASLFR_Flags1,                    FRF_DOPATTERNS,
  637.                                             ASLFR_InitialPattern,    "#?.iff",
  638.                                             TAG_DONE))
  639.         {
  640.             char filename[MAXFILENAME];
  641.             /* Create complete filename from ASL's dir and file */
  642.             strcpy(filename, loadreq->rf_Dir);
  643.             if(AddPart(filename, loadreq->rf_File, MAXFILENAME))
  644.             {
  645.                 IFFL_HANDLE handle;
  646.                 /* Try to open the IFF file */
  647.                 if(handle = IFFL_OpenIFF(filename, IFFL_MODE_READ))
  648.                 {
  649.                     LONG  count;
  650.                     UWORD colortable[256];
  651.                     /* Get colour information and change screen colours */
  652.                     count = IFFL_GetColorTab(handle, colortable);
  653.                     LoadRGB4(&(scr->ViewPort), colortable, count);
  654.                     /* If we can load the picture, update window's display */
  655.                     if(IFFL_DecodePic(handle, bitmap))
  656.                         CopySBitMap(drawwin->WLayer);
  657.                     else
  658.                         printf("Error: could not decode IFF picture\n");
  659.                     IFFL_CloseIFF(handle);
  660.                 }
  661.                 else
  662.                     printf("Error: could not open IFF file\n");
  663.             }
  664.             else
  665.                 printf("Error: could not make filename\n");
  666.         }
  667.         /* else: requester was cancelled */
  668.     }
  669.     else
  670.         printf("Error: could not allocate ASL (load) file request\n");
  671. }
  672.  
  673. /* Open an ASL save file requester */
  674. void save()
  675. {
  676.     /* Another way of saying "allocate if we haven't already" */
  677.     if(savereq || (savereq = (struct FileRequester*)AllocAslRequest(ASL_FileRequest,NULL)))
  678.     {
  679.         if(AslRequestTags(savereq,
  680.                                             ASLFR_TitleText,            "Save File",
  681.                                             ASLFR_Window,                    drawwin,
  682.                                             ASLFR_Flags1,                    FRF_DOPATTERNS | FRF_DOSAVEMODE,
  683.                                             ASLFR_InitialPattern,    "#?.iff",
  684.                                             ASLFR_InitialFile,        "picture.iff",
  685.                                             TAG_DONE))
  686.         {
  687.             char filename[MAXFILENAME];
  688.             /* Create complete filename from ASL's dir and file */
  689.             strcpy(filename, savereq->rf_Dir);
  690.             if(AddPart(filename, savereq->rf_File, MAXFILENAME))
  691.             {    
  692.                 /* Make sure our bitmap is the same as the display */
  693.                 SyncSBitMap(drawwin->WLayer);
  694.                 /* Try saving our bitmap, using the screen's colours */
  695.                 if(IFFL_SaveBitMap(filename, bitmap,
  696.                                                     scr->ViewPort.ColorMap->ColorTable,
  697.                                                     IFFL_COMPR_BYTERUN1) == 0)
  698.                     printf("Error: could not write IFF picture\n");
  699.             }
  700.             else
  701.                 printf("Error: could not make filename\n");
  702.         }
  703.         /* else: requester was cancelled */
  704.     }
  705.     else
  706.         printf("Error: could not allocate ASL (save) file request\n");
  707. }
  708.  
  709. /* Free any requesters that may have been allocated */
  710. void freeReqs()
  711. {
  712.     if(loadreq)
  713.     {
  714.         FreeAslRequest(loadreq);
  715.         loadreq = NULL;
  716.     }
  717.     if(savereq)
  718.     {
  719.         FreeAslRequest(savereq);
  720.         savereq = NULL;
  721.     }
  722. }
  723.  
  724. int createBitmap()
  725. {
  726.     /* The MEMF_CLEAR flag is vital, since it zeroes the allocated memory. */
  727.     /* Thus the pointers in the bitmap will be NULL, if we don't manage to */
  728.     /* allocate them properly. */
  729.     if(bitmap = AllocMem(sizeof(struct BitMap), MEMF_PUBLIC | MEMF_CLEAR))
  730.     {
  731.         int plane;
  732.         InitBitMap(bitmap, scr->BitMap.Depth, scr->Width, scr->Height);
  733.         for(plane = 0; plane < scr->BitMap.Depth; plane++)
  734.         {
  735.             bitmap->Planes[plane] = AllocRaster(scr->Width, scr->Height);
  736.             if(bitmap->Planes[plane] == NULL)
  737.                 return FALSE;
  738.         }
  739.         /* If we get here, we succeeded. */
  740.         return TRUE;
  741.     }
  742.     else
  743.         return FALSE;
  744. }
  745.  
  746. void freeBitmap()
  747. {
  748.     if(bitmap)
  749.     {
  750.         int plane;
  751.         for(plane = 0; plane < scr->BitMap.Depth; plane++)
  752.         {
  753.             if(bitmap->Planes[plane])
  754.                 FreeRaster(bitmap->Planes[plane], scr->Width, scr->Height);
  755.         }
  756.         FreeMem(bitmap, sizeof(struct BitMap));
  757.         bitmap = NULL;
  758.     }
  759. }
  760.